package modeller.databasedesignmodel.servicedemand.transaction.sqlquery.demandFetcher;

import modeller.databasedesignmodel.DatabaseDesign;
import modeller.databasedesignmodel.query.*;
import modeller.databasedesignmodel.relation.Relation;
import modeller.databasedesignmodel.servicedemand.IServiceDemand;
import modeller.databasedesignmodel.servicedemand.transaction.sqlquery.SQLQueryServiceDemand;
import modeller.databasedesignmodel.transaction.SQLQuery;

/**
 * Created by:  Jason Ye
 * Date:        25/03/2012
 * Time:        17:58
 */
public abstract class AbstractSQLQueryCalculatorVisitor implements ISQLQueryServiceDemandCalculator {


    protected DatabaseDesign design;

    AbstractSQLQueryCalculatorVisitor(DatabaseDesign d){
        this.design=d;
    }

    protected double getBDForQuery(SQLQuery query) {
        // assume one relation only, and it is at head

        Relation r = query.getRelation().first;
        return ((double) r.getBNumDbPages()) * design.getDAverageIOTime();
    }

    /*
     Heap calculator visitor calculate methods
     */
    @Override
    public IServiceDemand calculate(SequentialScanQuery query) {

        // BD
        return new SQLQueryServiceDemand(
                getBDForQuery(query),
                query.getRelation().getFirst()
        );

    }

    @Override
    public IServiceDemand calculate(EqualitySearchQuery query) {

        // 0.5BD
        return new SQLQueryServiceDemand(
                0.5 * getBDForQuery(query),
                query.getRelation().getFirst()
        );
    }

    @Override
    public IServiceDemand calculate(EqualityWithRangeSearchQuery query) {

        // BD
        return new SQLQueryServiceDemand(
                getBDForQuery(query),
                query.getRelation().getFirst()
        );
    }

    @Override
    public IServiceDemand calculate(InsertQuery query) {

        // 2D
        return new SQLQueryServiceDemand(
                2 * design.getDAverageIOTime(),
                query.getRelation().getFirst()
        );

    }

    @Override
    public IServiceDemand calculate(UpdateDeleteQuery query) {

        // Search + D = 0.5BD+D = D * (0.5B + 1)
        double BD = getBDForQuery(query);
        return new SQLQueryServiceDemand(
                (0.5 * BD) + design.getDAverageIOTime(),
                query.getRelation().getFirst()
        );
    }
}
